import os
import pandas as pd

from file_utils import normalize_jar_path

## Excel 解析类

class ExcelParser:
    @staticmethod
    def parse_replace_info(excel_file_path):
        """解析Excel文件，获取替换文件信息，支持识别文件夹（文件名以/或\结尾）"""
        if not os.path.exists(excel_file_path):
            return None, f"Excel文件不存在: {excel_file_path}"
    
        try:
            # 根据文件扩展名选择合适的引擎
            # .xlsx, .xlsm 等使用 openpyxl
            # .xls 使用 xlrd
            file_ext = os.path.splitext(excel_file_path)[1].lower()
            if file_ext in ['.xlsx', '.xlsm', '.xltx', '.xltm']:
                df = pd.read_excel(excel_file_path, engine='openpyxl')
            elif file_ext == '.xls':
                df = pd.read_excel(excel_file_path, engine='xlrd')
            else:
                df = pd.read_excel(excel_file_path)  # 让 pandas 自动选择引擎
            
            required_columns = ['路径', '文件名']
            optional_column = 'lib包'
            delete_column = '删除文件'
            folder_column = '文件夹'  # 新增：文件夹列（可选）
            
            for col in required_columns:
                if col not in df.columns:
                    return None, f"Excel文件缺少必要的表头: {col}"
            
            if optional_column not in df.columns:
                df[optional_column] = ""
            if delete_column not in df.columns:
                df[delete_column] = ""
            if folder_column not in df.columns:  # 新增：文件夹列为可选
                df[folder_column] = ""
            
            replace_info_list = []
            
            for index, row in df.iterrows():
                # 跳过空行
                if pd.isna(row[optional_column]) and pd.isna(row['路径']) and pd.isna(row['文件名']) and pd.isna(row[delete_column]):
                    continue
                
                # 检查必要字段是否为空（允许.jar在路径为空时默认放入BOOT-INF/lib）
                if pd.isna(row['文件名']):
                    return None, f"Excel文件第{index+1}行的'文件名'为空，请检查"
                
                # 处理路径格式
                lib_package = normalize_jar_path(str(row[optional_column]).strip() if not pd.isna(row[optional_column]) else "")
                path = '' if pd.isna(row['路径']) else normalize_jar_path(str(row['路径']).strip())
                filename = str(row['文件名']).strip()
                # 删除标记：接受 是/yes/true/1/试（兼容输入错误）
                delete_raw = str(row[delete_column]).strip() if not pd.isna(row[delete_column]) else ""
                delete_flag = delete_raw.lower() in ["是", "yes", "y", "true", "1", "试"]
                # 新增：处理文件夹列
                folder = '' if pd.isna(row[folder_column]) else str(row[folder_column]).strip()
                
                # 判断是否为文件夹（文件名以/或\结尾）
                is_folder = filename.endswith(('/','\\'))
                # 标准化文件夹名称（统一以/结尾）
                filename = filename.replace('\\', '/')
                
                # 构建目标路径
                is_jar_file = filename.lower().endswith('.jar')
                if is_jar_file and not path:
                    # 特殊规则：当路径为空且为.jar文件时，放在 BOOT-INF/lib/<filename>
                    dest_relative_path = f"BOOT-INF/lib/{filename}"
                else:
                    if lib_package:
                        parts = ["BOOT-INF", "lib", lib_package]
                    else:
                        parts = ["BOOT-INF", "classes"]

                    if path:
                        parts.append(path)
                    parts.append(filename)

                    dest_relative_path = '/'.join(parts)
                # 处理文件夹路径的末尾斜杠（确保一致性）
                if is_folder and not dest_relative_path.endswith('/'):
                    dest_relative_path += '/'
                
                replace_info_list.append({
                    'filename': filename,
                    'dest': dest_relative_path,
                    'lib包': lib_package,
                    '路径': path,
                    '文件夹': folder,  # 新增：文件夹字段
                    'row_num': index + 1,
                    'is_dir': is_folder,  # 新增字段标记是否为文件夹
                    '删除文件': delete_flag
                })
            
            if not replace_info_list:
                return None, "Excel文件中未找到有效的替换信息"
                
            return replace_info_list, "解析成功"
            
        except Exception as e:
            return None, f"解析Excel文件时出错: {str(e)}"